/******************************************************************************
 * Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
 * All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *****************************************************************************/
#if (1)

#include "myudb_usbdesc.h"
#include "drivers.h"
#include "myudb.h"

// request parameters
/** Language descriptor structure. This descriptor, located in FLASH memory, is returned when the host requests
 *  the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which indicate
 *  via the language ID table available at USB.org what languages the device supports for its string descriptors.
 */
static const USB_Descriptor_String_t language_desc = {{sizeof(USB_Descriptor_Header_t) + 2, DTYPE_String},
                                                      {LANGUAGE_ID_ENG}};

/** Manufacturer descriptor string. This is a Unicode string containing the manufacturer's details in human readable
 *  form, and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
 *  Descriptor.
 */
static const USB_Descriptor_String_t vendor_desc = {
    {sizeof(USB_Descriptor_Header_t) + sizeof(MYUDB_STRING_VENDOR) - 2, DTYPE_String},  // Header
    MYUDB_STRING_VENDOR};

/** Product descriptor string. This is a Unicode string containing the product's details in human readable form,
 *  and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
 *  Descriptor.
 */
static const USB_Descriptor_String_t product_desc = {
    {sizeof(USB_Descriptor_Header_t) + sizeof(MYUDB_STRING_PRODUCT) - 2, DTYPE_String},  // Header
    MYUDB_STRING_PRODUCT};

/** Serial number string. This is a Unicode string containing the device's unique serial number, expressed as a
 *  series of uppercase hexadecimal digits.
 */
static const USB_Descriptor_String_t serial_desc = {
    {sizeof(USB_Descriptor_Header_t) + sizeof(MYUDB_STRING_SERIAL) - 2, DTYPE_String},  // Header
    MYUDB_STRING_SERIAL};

static const USB_Descriptor_Device_t device_desc = {
    {sizeof(USB_Descriptor_Device_t), DTYPE_Device},  // Header
    0x0200,                                           // USBSpecification, USB 2.0
    USB_CSCP_NoDeviceClass,                           // Class
    USB_CSCP_NoDeviceSubclass,                        // SubClass
    USB_CSCP_NoDeviceProtocol,                        // Protocol
    8,                 // Endpoint0Size, Maximum Packet Size for Zero Endpoint. Valid Sizes are 8, 16, 32, 64
    MYUDB_ID_VENDOR,   // VendorID
    MYUDB_ID_PRODUCT,  // ProductID
    MYUDB_ID_VERSION /* 0x0100 */,  // .ReleaseNumber
    MYUDB_USB_STRING_VENDOR,        // .ManufacturerStrIndex
    MYUDB_USB_STRING_PRODUCT,       // .ProductStrIndex
    0,                              // .SerialNumStrIndex, iSerialNumber
    1};

static const MYUDB_USB_Descriptor_Configuration_t configuration_desc = {
    {
        {sizeof(USB_Descriptor_Configuration_Header_t), DTYPE_Configuration},  // Length, type
        sizeof(MYUDB_USB_Descriptor_Configuration_t),                          // TotalLength: variable
        2,                                                                     // NumInterfaces
        1,                                                                     // Configuration index
        NO_DESCRIPTOR,                                                         // Configuration String
        USB_CONFIG_ATTR_RESERVED,                                              // Attributes
        USB_CONFIG_POWER_MA(100)                                               // MaxPower = 100mA
    },
    // printer_interface
    {
        {sizeof(USB_Descriptor_Interface_t), DTYPE_Interface},
        0,
        0,                                // AlternateSetting
        2,                                // bNumEndpoints
        PRNT_CSCP_PrinterClass,           // bInterfaceclass ->Printer
        PRNT_CSCP_PrinterSubclass,        // bInterfaceSubClass -> Control
        PRNT_CSCP_BidirectionalProtocol,  // bInterfaceProtocol
        NO_DESCRIPTOR  // iInterface,  same as iProduct in USB_Descriptor_Device_t, or else not working
    },
    // printer_in_endpoint
    {
        {sizeof(USB_Descriptor_Endpoint_t), DTYPE_Endpoint},  // length, bDescriptorType
        ENDPOINT_DIR_IN | MYUDB_EDP_IN_HCI,                   // endpoint id
        EP_TYPE_BULK,                                         // endpoint type
        0x0040,                                               // wMaxPacketSize
        0                                                     // bInterval
    },
    // printer_out_endpoint
    {
        {sizeof(USB_Descriptor_Endpoint_t), DTYPE_Endpoint},  // length, bDescriptorType
        MYUDB_EDP_OUT_HCI,                                    // endpoint id
        EP_TYPE_BULK,                                         // endpoint type
        0x0040,                                               // wMaxPacketSize
        0                                                     // polling bInterval. valid for iso or interrupt type
    },

    // printer_interface
    {
        {sizeof(USB_Descriptor_Interface_t), DTYPE_Interface},
        1,
        0,                                // AlternateSetting
        2,                                // bNumEndpoints
        PRNT_CSCP_PrinterClass,           // bInterfaceclass ->Printer
        PRNT_CSCP_PrinterSubclass,        // bInterfaceSubClass -> Control
        PRNT_CSCP_BidirectionalProtocol,  // bInterfaceProtocol
        NO_DESCRIPTOR  // iInterface,  same as iProduct in USB_Descriptor_Device_t, or else not working
    },
    // printer_in_endpoint
    {
        {sizeof(USB_Descriptor_Endpoint_t), DTYPE_Endpoint},  // length, bDescriptorType
        ENDPOINT_DIR_IN | MYUDB_EDP_IN_VCD,                   // endpoint id
        EP_TYPE_BULK,                                         // endpoint type
        0x0040,                                               // wMaxPacketSize
        0                                                     // bInterval
    },
    // printer_out_endpoint
    {
        {sizeof(USB_Descriptor_Endpoint_t), DTYPE_Endpoint},  // length, bDescriptorType
        MYUDB_EDP_OUT_VCD,                                    // endpoint id
        EP_TYPE_BULK,                                         // endpoint type
        0x0040,                                               // wMaxPacketSize
        0                                                     // polling bInterval. valid for iso or interrupt type
    },
};

u8 *myudb_usbdesc_get_language(void)
{
    return (u8 *)(&language_desc);
}

u8 *myudb_usbdesc_get_vendor(void)
{
    return (u8 *)(&vendor_desc);
}

u8 *myudb_usbdesc_get_product(void)
{
    return (u8 *)(&product_desc);
}
u8 *myudb_usbdesc_get_serial(void)
{
    return (u8 *)(&serial_desc);
}

u8 *myudb_usbdesc_get_device(void)
{
    return (u8 *)(&device_desc);
}

u8 *myudb_usbdesc_get_configuration(void)
{
    return (u8 *)(&configuration_desc);
}

#endif
